<?php
##
## Copyright (c) 1999-2000 Internet Images Srl
##                    Massimiliano Masserelli
##
## Depends on ooh_forms
##
## $Id: tpl_form.inc,v 1.3 2002/03/19 22:32:25 layne_weathers Exp $
##

class tpl_form {
  var $classname = "tpl_form"; # Used for serialization AND in display()
                               # to determine the filename of template
                               # containing html/php code needed to 
                               # actually render the form

  var $form_data;            # Holds form info (form object), is
                             # initialized in the init() "constructor".
                             
  var $values = array();     # Must be inizialized by a call to the
                             # init() "constructor".
                             # All data that this form produces
                             # for application use shold be
                             # appended there
                             
  var $error = "";           # Contains error messages generated by
                             # validate() and validate_input() methods.
                             
  var $has_defaults = 0;     # Flag, form default values were passed
                             # via set_default_values() method. Should
                             # not be tampered with by the user.

  # This is a sort of constructor for the class. $values
  # is an array used to store form values. The class
  # writes data into it, but may also use it to obtain
  # data from the application
  function init($values) {
    if (! is_array($values)) {
      $this->values = array();
    } else {
      $this->values = $values;
    }
    return true;
  }

  # Init the form object, which will contain all fields info. The
  # hidden field form_name is used by other methods to determine
  # if form has been submitted by the user.
  # You shouldn't override this in descendants, use setup_fields()
  # instead.
  function setup() {
    $this->form_data = new form;
    $this->form_data->add_element(array(
      "name"=>"form_name",
      "value"=>$this->classname,
      "type"=>"hidden"
    ));
    $this->setup_fields();
    return true;
  }

  # Override this method in order to provide form fields definition
  # that suit your needs.
  function setup_fields() {
    return true;
  }

  # Returns an array containing all data submitted by the user for
  # the form. This array is intended to be passed to set_defaults_values()
  # some time later.
  function get_default_values() {
    if (! is_object($this->form_data)) {
      $this->setup();
    }
    $fv = array();
    for (reset($this->form_data->elements); $elrec = current($this->form_data->elements); next($this->form_data->elements)) {
      $el = $elrec["ob"];
      $vn = $el->name;
      global $$vn;
      $fv[$el->name] = $$vn;
    }
    return $fv;
  }

  # Restore form defaults from an array as returned by get_default_values()
  function set_default_values($fv) {
    if (! is_object($this->form_data)) {
      $this->setup();
    }
    if (! is_array($fv)) {
      return false;
    }
    while (list($var, $value) = each($fv)) {
      global $$var;
      $$var = $value;
    }
    $this->has_defaults = 1;
    return true;
  }

  # Validates user input. This method should not be overridden in 
  # descendants. See validate_input() instead. Returns false on
  # error and sets $this->error accordingly.
  function validate() {
    global $form_name;
    if (! is_object($this->form_data)) {
      $this->setup();
    }
    if ($form_name == $this->classname) {
      $err = $this->form_data->validate("ok");
      if ($err == "ok") {
        return $this->validate_input();
      } else {
        $this->error = $err;
        return false;
      }
    } else {
      return false;
    }
  }
  
  # This method should be overridden in descendants, in order to 
  # provided complex validation methods (i.e. field2 should not be
  # empty IF field1 = "other").
  # Should return false on error and set $this->error accordingly.
  function validate_input() {
    $this->error = "";
    return true;
  }

  # Actually display form fields. This method should not be overridden
  # in descendants. User should provide a file named as the derived 
  # class and with ".ihtml" extension. 
  function display() {
    global $sess;
    global $form_name;

    // I guess some people use $PHP_SELF in their include files
	// otherwise these should be removed completely - layne_weathers
    global $HTTP_SERVER_VARS;
    $PHP_SELF = $HTTP_SERVER_VARS["PHP_SELF"];
    
    if (! is_object($this->form_data)) {
      $this->setup();
    }
    if (($form_name == $this->classname) || $this->has_defaults) {
      $this->form_data->load_defaults();
    }
    include($this->classname . ".ihtml");

    return true;
  }

  # Process user data. This method should not be overridden by descendants.
  # See process_input() and process_default() instead. Returns true on
  # success.
  function process() {
    if ($this->validate()) {
      return $this->process_input();
    } else {
      return $this->process_default();
    }
  }

  # This method should be overridden in descendants. It is executed after
  # validation has taken place. The data passed to the form should be
  # used to fill $this->values array (eventually after a database lookup
  # or whatever).
  function process_input() {
    return true;
  }

  # This method should be overridden in descendants. It is executed when
  # form validation fails or before presenting the form for the first 
  # time. Should be used to inhibit form displaying if data can be
  # extracted from previous actions, divination, penguin fly watching or
  # whatever.
  function process_default() {
    return false;
  }

  # This method should not be overridden. It is intended as the main
  # interface between the application and the form. Once the form has
  # been properly derived to suit designer's needs, applications calls
  # $myform->get_values() and obtains an array containing user supplied
  # data. Failing that, the application should call $form->display()
  # to (re)present the form to the user.
  function get_values() {
    if ($this->process()) {
      return $this->values;
    } else {
      return false;
    }
  }

  # Sort of "destructor". There's no real need to call it, except maybe
  # freeing some memory. May be called from the application, but is 
  # otherwise not executed. Returns true.
  function clear() {
    $this->has_defaults = 0;
    $this->values = array();
    $this->error = "";
    unset($this->form_data);
    return true;
  }
}
?>
